#include "gameinfo_service.h"
#include "context.h"
#include "streamdata.h"
#include "log.h"
#include "gameinfomgr.h"
#include "util.h"


static bool __init__ = GameInfoService::Instance()->Init();

bool GameInfoService::Init()
{
    Ctx.msg_router.BindMsg(gameinfo_proto::GAMEINFO_CMD_INFO_RESP, std::bind(&GameInfoService::OnGameinfo, this, std::placeholders::_1));

    return true;
}

bool GameInfoService::HandleGameInfo(const std::uint32_t agency_id, const std::uint32_t game, std::string&& trans, Sence sence)
{
    log_debug("enter");
    StreamData stream_data;
    StreamDataWriter write(stream_data);
    write.Write<Sence>(sence);
    write.WriteString(trans);
    write.WriteInt64(CTools::GetUnixTimeMs());

    gameinfo_proto::InfoReq info_req;
    info_req.set_agency_id(agency_id);
    info_req.set_game(game);
    info_req.set_trans(std::move(stream_data.Data()));
    Ctx.host->MtSendtoSrv(gameinfo_proto::GAMEINFO_CMD_INFO_REQ, SERVER_TYPE_GAME_INFO, &info_req, 0);
    return true;
}

void GameInfoService::OnGameinfo(MsgData&& data)
{
    log_debug("enter");
    do
    {
        gameinfo_proto::InfoResp info_resp;
        if (!info_resp.ParseFromArray(data.data.c_str(), data.data.size()))
        {
            log_error("parser gameinfo_proto::LauchUrlResp failed, stype:%hu,svid:%u,uuid:%u", data.svtype, data.svid, data.uuid);
            break;
        }

        StreamData stream_data(std::move(*info_resp.mutable_trans()));
        StreamDataReader reader(stream_data);
        Sence sence = reader.Read<Sence>();
        std::string trans = reader.ReadString();
        std::uint64_t req_time = reader.ReadInt64();
        std::uint64_t resp_time = CTools::GetUnixTimeMs();
        std::uint64_t cost_time = resp_time-req_time;
        if (cost_time > 50000)  // 大于50ms返回需要预警
        {
            log_warning("agency:%u,gameid:%u get info cost %lu us", info_resp.gameinfo().agency_id(), info_resp.gameinfo().game(), cost_time);
        }
        else
        {
            log_debug("agency:%u,gameid:%u get info cost %lu us", info_resp.gameinfo().agency_id(), info_resp.gameinfo().game(), cost_time);
        }

        auto it = m_gameinfo_listen.find(sence);
        if (it == m_gameinfo_listen.end())
        {
            log_info("sence:%d not listen, stype:%u,svid:%u,uuid:%u", sence, data.svtype, data.svid, data.uuid);
            break;
        }
        try
        {
            log_debug("resp:%s", info_resp.ShortDebugString().c_str());
            
            if (info_resp.err_code() == 0)
            {
                stGameInfo gameinfo;
                gameinfo.CopyFrom(info_resp.gameinfo());
                GameInfoMgr::Instance()->Update(std::move(gameinfo));

                stGameInfo* p_gameinfo = GameInfoMgr::Instance()->Get(info_resp.gameinfo().agency_id(), info_resp.gameinfo().game());
                it->second(p_gameinfo, info_resp.err_code(), std::move(trans));
            }
            else
            {
                it->second(nullptr, info_resp.err_code(), std::move(trans));
            }
        }
        catch(const std::exception& e)
        {
            log_error("catch exception:%s, sence:%d, stype:%hu,svid:%u,uuid:%u,msg:%s", e.what(), sence, data.svtype, data.svid, data.uuid, info_resp.ShortDebugString().c_str());
        }
        catch(...)
        {
            log_error("catch unknown exception, sence:%d, stype:%hu,svid:%u,uuid:%u,msg:%s", sence, data.svtype, data.svid, data.uuid, info_resp.ShortDebugString().c_str());
        }
    } while(false);
}




